package com.lxt.ScreencastGallery;

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;

import androidx.appcompat.widget.AppCompatImageView;

/**
 * 支持缩放和平移的ImageView
 */
public class ZoomableImageView extends AppCompatImageView implements View.OnTouchListener,
        ScaleGestureDetector.OnScaleGestureListener {

    private static final int NONE = 0;
    private static final int DRAG = 1;
    private static final int ZOOM = 2;

    private Matrix matrix;
    private int mode = NONE;

    private PointF last = new PointF();
    private PointF start = new PointF();
    private float minScale = 0.5f; // 允许缩小到原图的一半
    private float maxScale = 4f;
    private float[] m;

    private int viewWidth, viewHeight;
    private static final int CLICK = 3;
    private float saveScale = 1f;
    private int oldMeasuredWidth, oldMeasuredHeight;

    private ScaleGestureDetector mScaleDetector;

    // 图片原始尺寸
    private float origWidth, origHeight;
    // 当前图片显示尺寸
    private float currentWidth, currentHeight;
    // 图片在视图中的位置
    private float currentTranslateX, currentTranslateY;

    // 缩放中心点
    private float focusX, focusY;

    public ZoomableImageView(Context context) {
        super(context);
        sharedConstructing(context);
    }

    public ZoomableImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        sharedConstructing(context);
    }

    private void sharedConstructing(Context context) {
        super.setClickable(true);
        this.mScaleDetector = new ScaleGestureDetector(context, this);
        matrix = new Matrix();
        m = new float[9];
        setImageMatrix(matrix);
        setScaleType(ScaleType.MATRIX);

        setOnTouchListener(this);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        viewWidth = MeasureSpec.getSize(widthMeasureSpec);
        viewHeight = MeasureSpec.getSize(heightMeasureSpec);

        if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight
                || viewWidth == 0 || viewHeight == 0)
            return;
        oldMeasuredHeight = viewHeight;
        oldMeasuredWidth = viewWidth;

        if (saveScale == 1) {
            fitToScreen();
        }
    }

    public void fitToScreen() {
        Drawable drawable = getDrawable();
        if (drawable == null) {
            return;
        }

        // 获取图片原始尺寸
        origWidth = drawable.getIntrinsicWidth();
        origHeight = drawable.getIntrinsicHeight();

        if (origWidth <= 0 || origHeight <= 0) {
            return;
        }

        // 计算适应显示区域的缩放比例
        float scaleX = (float) viewWidth / origWidth;
        float scaleY = (float) viewHeight / origHeight;
        float scale = Math.min(scaleX, scaleY);

        // 重置矩阵
        matrix.reset();
        matrix.postScale(scale, scale);

        // 计算居中偏移量
        currentWidth = origWidth * scale;
        currentHeight = origHeight * scale;
        currentTranslateX = (viewWidth - currentWidth) / 2.0f;
        currentTranslateY = (viewHeight - currentHeight) / 2.0f;

        matrix.postTranslate(currentTranslateX, currentTranslateY);
        saveScale = scale;

        setImageMatrix(matrix);
        invalidate();
    }

    /**
     * 按宽度适配图片显示，优化对齐方式避免黑边
     */
    public void fitToWidth() {
        Drawable drawable = getDrawable();
        if (drawable == null) {
            return;
        }

        // 获取图片原始尺寸
        origWidth = drawable.getIntrinsicWidth();
        origHeight = drawable.getIntrinsicHeight();

        if (origWidth <= 0 || origHeight <= 0) {
            return;
        }

        // 计算按宽度适配的缩放比例
        float scale = (float) viewWidth / origWidth;

        // 重置矩阵
        matrix.reset();
        matrix.postScale(scale, scale);

        // 计算位置偏移量
        currentWidth = origWidth * scale;
        currentHeight = origHeight * scale;
        currentTranslateX = 0; // 左对齐

        // 垂直方向处理
        if (currentHeight > viewHeight) {
            // 图片高度超过视图高度，顶部对齐以便查看图片上部分内容
            currentTranslateY = 0;
        } else {
            // 图片高度小于视图高度，居中显示以避免上下黑边
            currentTranslateY = (viewHeight - currentHeight) / 2.0f;
        }

        matrix.postTranslate(currentTranslateX, currentTranslateY);
        saveScale = scale;

        setImageMatrix(matrix);
        invalidate();
    }





    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {
        mode = ZOOM;
        // 记录缩放中心点
        focusX = detector.getFocusX();
        focusY = detector.getFocusY();
        return true;
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector detector) {
        mode = NONE;
        fixTrans();
    }

    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        if (getDrawable() == null) {
            return true;
        }

        float scaleFactor = detector.getScaleFactor();

        // 针对缩小和放大分别处理敏感度
        if (scaleFactor < 1.0f) {
            // 缩小操作 - 提高敏感度
            float shrinkSensitivity = 4.0f;  // 缩小时的敏感度系数
            scaleFactor = 1.0f + (scaleFactor - 1.0f) * shrinkSensitivity;
        } else {
            // 放大操作 - 适度敏感度
            float expandSensitivity = 2.5f;   // 放大时的敏感度系数
            scaleFactor = 1.0f + (scaleFactor - 1.0f) * expandSensitivity;
        }

        // 限制极端缩放因子
        if (scaleFactor > 1.5f) scaleFactor = 1.5f;
        if (scaleFactor < 0.5f) scaleFactor = 0.5f;

        float originalScale = saveScale;
        saveScale *= scaleFactor;

        // 限制缩放范围
        if (saveScale > maxScale) {
            saveScale = maxScale;
            scaleFactor = maxScale / originalScale;
        } else if (saveScale < minScale) {
            saveScale = minScale;
            scaleFactor = minScale / originalScale;
        }

        // 使用手势的焦点作为缩放中心
        focusX = detector.getFocusX();
        focusY = detector.getFocusY();

        matrix.postScale(scaleFactor, scaleFactor, focusX, focusY);

        // 更新当前图片尺寸
        currentWidth = origWidth * saveScale;
        currentHeight = origHeight * saveScale;

        // 修复位置，确保图片不会移出显示区域
        fixTrans();

        setImageMatrix(matrix);
        invalidate();

        return true;
    }






    /**
     * 修复位置，确保图片在显示区域内
     */
    private void fixTrans() {
        matrix.getValues(m);
        float transX = m[Matrix.MTRANS_X];
        float transY = m[Matrix.MTRANS_Y];

        float fixTransX = 0;
        float fixTransY = 0;

        // 水平方向边界检查
        if (currentWidth > viewWidth) {
            // 图片宽度大于视图宽度
            if (transX > 0) {
                // 右边出现空白，向左移动
                fixTransX = -transX;
            } else if (transX + currentWidth < viewWidth) {
                // 左边出现空白，向右移动
                fixTransX = viewWidth - (transX + currentWidth);
            }
        } else {
            // 图片宽度小于等于视图宽度，居中显示
            float targetX = (viewWidth - currentWidth) / 2;
            fixTransX = targetX - transX;
        }

        // 垂直方向边界检查
        if (currentHeight > viewHeight) {
            // 图片高度大于视图高度
            if (transY > 0) {
                // 底部出现空白，向上移动
                fixTransY = -transY;
            } else if (transY + currentHeight < viewHeight) {
                // 顶部出现空白，向下移动
                fixTransY = viewHeight - (transY + currentHeight);
            }
        } else {
            // 图片高度小于等于视图高度，居中显示
            float targetY = (viewHeight - currentHeight) / 2;
            fixTransY = targetY - transY;
        }

        if (fixTransX != 0 || fixTransY != 0) {
            matrix.postTranslate(fixTransX, fixTransY);
            currentTranslateX = transX + fixTransX;
            currentTranslateY = transY + fixTransY;
        } else {
            currentTranslateX = transX;
            currentTranslateY = transY;
        }
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        mScaleDetector.onTouchEvent(event);
        PointF curr = new PointF(event.getX(), event.getY());

        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                last.set(curr);
                start.set(last);
                mode = DRAG;
                break;

            case MotionEvent.ACTION_POINTER_DOWN:
                mode = ZOOM;
                break;

            case MotionEvent.ACTION_MOVE:
                if (mode == DRAG) {
                    float deltaX = curr.x - last.x;
                    float deltaY = curr.y - last.y;

                    // 只有在图片尺寸大于视图尺寸时才允许拖动
                    if (currentWidth > viewWidth || currentHeight > viewHeight) {
                        // 应用拖动
                        matrix.postTranslate(deltaX, deltaY);

                        // 修复位置，确保不会拖出边界
                        fixTrans();

                        setImageMatrix(matrix);
                        invalidate();
                    }
                    last.set(curr.x, curr.y);
                }
                break;

            case MotionEvent.ACTION_UP:
                mode = NONE;
                int xDiff = (int) Math.abs(curr.x - start.x);
                int yDiff = (int) Math.abs(curr.y - start.y);
                if (xDiff < CLICK && yDiff < CLICK) {
                    performClick();
                }
                break;

            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                break;
        }

        return true;
    }

    public void resetZoom() {
        saveScale = 1f;
        fitToScreen();
    }

    /**
     * 获取当前缩放比例
     */
    public float getScale() {
        return saveScale;
    }

    public void setOnDoubleClickListener(final OnDoubleClickListener listener) {
        setOnTouchListener(new OnTouchListener() {
            private int clickCount = 0;
            private long lastClickTime = 0;
            private static final int DOUBLE_CLICK_TIME_DELTA = 300; // milliseconds

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_UP) {
                    long clickTime = System.currentTimeMillis();
                    if (clickTime - lastClickTime < DOUBLE_CLICK_TIME_DELTA) {
                        clickCount++;
                        if (clickCount == 2) {
                            // 双击缩放逻辑
                            if (saveScale > 1.0f) {
                                // 如果已经放大，则重置到适应屏幕大小
                                resetZoom();
                            } else {
                                // 如果未放大，则放大到2倍
                                zoomTo(2.0f, event.getX(), event.getY());
                            }
                            clickCount = 0;
                            return true; // 消费这个事件
                        }
                    } else {
                        clickCount = 1;
                    }
                    lastClickTime = clickTime;
                }

                // 仍然处理原有的触摸事件
                return ZoomableImageView.this.onTouch(v, event);
            }
        });
    }


    /**
     * 缩放到指定比例
     * @param targetScale 目标缩放比例
     * @param focusX 缩放中心点X坐标
     * @param focusY 缩放中心点Y坐标
     */
    public void zoomTo(float targetScale, float focusX, float focusY) {
        if (getDrawable() == null) {
            return;
        }

        // 限制目标缩放比例在有效范围内
        targetScale = Math.max(minScale, Math.min(targetScale, maxScale));

        float scaleFactor = targetScale / saveScale;
        saveScale = targetScale;

        matrix.postScale(scaleFactor, scaleFactor, focusX, focusY);

        // 更新当前图片尺寸
        currentWidth = origWidth * saveScale;
        currentHeight = origHeight * saveScale;

        // 修复位置
        fixTrans();

        setImageMatrix(matrix);
        invalidate();
    }



    public interface OnDoubleClickListener {
        void onDoubleClick();
    }
}